package base.core;

import base.definition.JsonFieldDefinition;
import base.originBase.BaseParameter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import lombok.Setter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.testng.annotations.DataProvider;

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 在这个类中会分析xx.json将测试数据反序列化为对象给后续程序提供数据
 */
public class TestBase {
    public Logger logger = LogManager.getLogger(this.getClass());
    private final String defaultParam = "defaultParam.json";
    private final String DEFAULT_PATH = "testsuites";
    private final String DEFAULT_METHOD = "GET";
    //用JsonFieldDefinition 来添加自定义json数据格式字段
    @Setter
    private JsonFieldDefinition jsonFieldDefinition = new JsonFieldDefinition();

    public TestBase() {
    }

    @DataProvider(name = "data")
    public Object[][] getTestData() throws Exception {
        String className = this.getClass().getName();
        if (!className.contains(DEFAULT_PATH)) {
            this.logger.error("测试用例 " + className + " 父目录名称错误, 应为" + DEFAULT_PATH);
            throw new Exception("测试用例 " + className + " 父目录名称错误, 应为" + DEFAULT_PATH);
        } else {
            String dataAbsolutePath = getDataAbsolutePath(className, "json");
            return getTestData(dataAbsolutePath);
        }
    }

    private String getDataAbsolutePath(String className, String fileType) throws FileNotFoundException {
        List<String> paths = Arrays.stream(("src.test.java." + className).split("\\.")).map(x -> {
            return x.equals(DEFAULT_PATH) ? "data" : x;
        }).collect(Collectors.toList());
        String baseDir = System.getProperty("user.dir");
        paths.add(0, baseDir);
        String absolutePath = String.join(File.separator, paths) + "." + fileType;
        logger.info("读取文件：" + absolutePath);
        if (!new File(absolutePath).exists()) {
            logger.error("不存在文件：" + absolutePath);
            throw new FileNotFoundException(absolutePath);
        }
        return absolutePath;
    }

    /**
     * 固定有5个json字段
     * 分别是：0.请求参数。1.返回值。2.调用方法。3.URL，4.描述。
     * 当respons的值仅仅为 defaultParam.json时候，就读取当前目录下的defaultParam.json文件
     * 这个defaultParam.json文件可以作为多个接口的统一参数
     *
     * @param fileAbsolutePath
     * @return
     */
    private Object[][] getTestData(String fileAbsolutePath) {
        String contentString = readToString(fileAbsolutePath);
        JSONArray nativeJson = null;

        try {
            logger.info(contentString);
            nativeJson = JSONArray.parseArray(contentString);
        } catch (Exception e) {
            logger.error(contentString + "格式错误");
        }

        int len = nativeJson.size();
        //默认包含5个字段0.请求参数。1.返回值。2.调用方法。3.URL，4.描述。
        Object[][] results = new Object[len][2];//comments 和 basepParamter

        for (int i = 0; i < len; ++i) {
            results[i][0] = nativeJson.getJSONObject(i).getString(jsonFieldDefinition.JSON_COMMENTS);
            results[i][1] = new ArrayList<BaseParameter>();
            List<BaseParameter> list = (List<BaseParameter>) results[i][1];

            if (nativeJson.getJSONObject(i).getString(jsonFieldDefinition.JSON_STEP) != null) {
                multipartyStep(list, nativeJson.getJSONObject(i).getJSONArray(jsonFieldDefinition.JSON_STEP));
            } else {
                singleStep(list, nativeJson.getJSONObject(i));
            }
            uniteParameter();
        }
        logger.info("完成入参数据解析：共计" + results.length + "个CASE。\n");
        return results;
    }

    protected void uniteParameter(){
        //未调试统一默认参数功能
//            JSONObject share = (JSONObject)objects[i][0];
//            if(share != null){
//                Object objsha = share.get("");
//                if (objsha == defaultParam)
//                    objects[i][0] = mergeJSON(objects[i][0]);
//            }
    }

    private void singleStep(List<BaseParameter> list, JSONObject json) {
        Object[] objects = new Object[jsonFieldDefinition.jsonSegments.length];
        setDefaultParams(objects);
        for (int index = 0; index < jsonFieldDefinition.jsonSegments.length; ++index) {
            objects[index] = json.get(jsonFieldDefinition.jsonSegments[index]);
        }
        list.add(convertToParameter(objects));
    }

    private void multipartyStep(List<BaseParameter> list, JSONArray steps) {
        for (int i = 0; i < steps.size(); ++i) {
            JSONObject json = steps.getJSONObject(i);
            singleStep(list, json);
        }
    }

    //给他们填充上默认字段
    private void setDefaultParams(Object[] objects) {
        //get
        objects[2] = DEFAULT_METHOD;
        // comments 描述
        objects[objects.length - 1] = "false";
        //headers
        objects[5] = "";
    }

    //创建最终的BaseParameter
    public BaseParameter convertToParameter(Object[] objs) {
        try {
            return (BaseParameter) BaseParameter.class.getDeclaredConstructors()[0].newInstance(objs);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 读取JSON文件，并转换为UTF-8的字符
     *
     * @param fileName 文件绝对路径
     * @return
     */
    private String readToString(String fileName) {
        File file = new File(fileName);
        Long fileLength = file.length();
        byte[] contents = new byte[fileLength.intValue()];
        FileInputStream in = null;
        try {
            in = new FileInputStream(file);
            in.read(contents);
        } catch (IOException ex) {
            logger.error(ex.getMessage(), ex);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.error("关闭文件失败!", e.getMessage(), e);
                }
            }
        }

        try {
            return new String(contents, "utf-8");
        } catch (UnsupportedEncodingException ex) {
            logger.error("The OS does not support utf-8" + "; " + ex.getMessage(), ex);
            return null;
        }
    }

    /**
     * 读取指定文件做json数据
     *
     * @param json
     * @return
     */
    protected JSONObject mergeJSON(Object json) {
        JSONObject defaultParamJSON = loadFile2JSON(defaultParam);
        if (defaultParamJSON != null && defaultParamJSON.size() != 0) {
            Set set = defaultParamJSON.keySet();
            Iterator iterator = set.iterator();

            String jsonString;
            Object value;
            String origin;
            for (jsonString = json.toString(); iterator.hasNext(); jsonString = jsonString.replace(origin, value.toString())) {
                String key = iterator.next().toString();
                value = defaultParamJSON.get(key);
                origin = "\"$" + key + "\"";
            }

            return (JSONObject) JSONObject.parse(jsonString);
        } else {
            return (JSONObject) json;
        }
    }

    private JSONObject loadFile2JSON(String filePath) {
        String results = "";
        InputStream inputStream = null;
        try {
            inputStream = TestBase.class.getClassLoader().getResourceAsStream(filePath);
            int tmp;
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
            while ((tmp = inputStreamReader.read()) != -1) {
                results = results + (char) tmp;
            }
            return JSON.parseObject(results);
        } catch (Exception ex) {
            logger.error("read file error,reason: {}", ex.getMessage(), ex);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    logger.error("文件不存在: {}" + filePath, e.getMessage(), e);
                }
            }
        }

        return null;
    }
}

